package com.ruoyi.web.controller.system;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.MessageUtil;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.mail.MailUtil;
import com.ruoyi.common.utils.sign.Md5Utils;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.framework.web.domain.server.Sys;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.web.bind.annotation.*;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysMenu;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginBody;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.framework.web.service.SysLoginService;
import com.ruoyi.framework.web.service.SysPermissionService;
import com.ruoyi.system.service.ISysMenuService;

import javax.servlet.http.HttpServletRequest;

/**
 * 登录验证
 *
 * @author ruoyi
 */
@RestController
@RequestMapping("/system/loginAndRegister")
public class CustomLoginController extends BaseController
{
    @Autowired
    private SysLoginService loginService;

    @Autowired
    private ISysMenuService menuService;

    @Autowired
    private SysPermissionService permissionService;

    @Autowired
    private MessageUtil messageUtil;

    @Autowired
    private ISysUserService sysUserService;

    @Autowired
    private MailUtil mailUtil;


    @Autowired
    private RedisCache redisCache;


    // 用户名
    @Value("${ykToken.appCode}")
    private String appCode;
    // 密码
    @Value("${ykToken.secret}")
    private String secret;


    /**
     * 获取token（第三方接口）
     * @param
     * @return 结果
     */
    @PostMapping("/createYkToken")
    public AjaxResult createYkToken(HttpServletRequest request)
    {
        AjaxResult ajax = AjaxResult.success();

        String acceptAppCode = request.getHeader("appCode"); //用户名
        String acceptSecret = request.getHeader("secret"); //密码
        //判断是否相同
        if(!acceptAppCode.equals(appCode)){
            return AjaxResult.error("appCode不正确");
        }
        if(!acceptSecret.equals(secret)){
            return AjaxResult.error("secret不正确");
        }
        String token = loginService.getYkToken(acceptAppCode, acceptSecret);
        ajax.put(Constants.TOKEN, token);
        return ajax;
    }

    /**
     * 登录方法
     *
     * @param loginBody 登录信息
     * @return 结果
     */
    @PostMapping("/login1")
    public AjaxResult login1(@RequestBody LoginBody loginBody)
    {
        AjaxResult ajax = AjaxResult.success();
        // 生成令牌
        String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),
                loginBody.getUuid());
        ajax.put(Constants.TOKEN, token);
        return ajax;
    }

    /**
     * 获取用户信息
     *
     * @return 用户信息
     */
    @GetMapping("getInfo")
    public AjaxResult getInfo()
    {
        SysUser user = SecurityUtils.getLoginUser().getUser();
        // 角色集合
        Set<String> roles = permissionService.getRolePermission(user);
        // 权限集合
        Set<String> permissions = permissionService.getMenuPermission(user);
        AjaxResult ajax = AjaxResult.success();
        ajax.put("user", user);
        ajax.put("roles", roles);
        ajax.put("permissions", permissions);
        return ajax;
    }

    /**
     * 获取路由信息
     *
     * @return 路由信息
     */
    @GetMapping("getRouters")
    public AjaxResult getRouters()
    {
        Long userId = SecurityUtils.getUserId();
        List<SysMenu> menus = menuService.selectMenuTreeByUserId(userId);
        return AjaxResult.success(menuService.buildMenus(menus));
    }


    /**
     * 新增功能
     */

    // 获取验证码
    @PostMapping(value = "/getCode")
    public AjaxResult getCode(@RequestBody Map map) {
        if(map.get("registerType") == null){
            return AjaxResult.error("登录类型不能为空");
        }
        Integer type = Integer.parseInt(map.get("registerType").toString());
        long rand = Math.round(Math.random() * 10000);
        String code = String.valueOf(rand);
        JSONObject obj = new JSONObject();
        obj.put("code", code);
        String uuid = IdUtils.simpleUUID();//生成uuid
        String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + code + uuid; //生成校验码

        try {
            if(type == 1){ //登录类型 1代表手机
                String phonenumber = map.get("phonenumber") == null?"":map.get("phonenumber").toString();
                if(StringUtils.isEmpty(phonenumber)){
                    return AjaxResult.error("手机号不能为空");
                }
                messageUtil.sendSms(phonenumber, "SMS_196270385", obj);
                redisCache.setCacheObject(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);
            }else if(type == 2){ //代表邮箱
                String email = map.get("email") == null?"":map.get("email").toString();
                if(StringUtils.isEmpty(email)){
                    return AjaxResult.error("邮箱不能为空");
                }
                mailUtil.sendMailOne(email,"获取验证码",code);
                redisCache.setCacheObject(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        //对四位验证码进行加密
        return AjaxResult.success(uuid);
    }

    /**
     * @param sysUser 是否注册（手机注册或者邮箱注册）
     * @return 结果
     */
    @PostMapping("/isRegister")
    public AjaxResult isRegister(@RequestBody SysUser sysUser)
    {
        int n = 0;
        //注册类型
        String registerType = sysUser.getRegisterType();//注册类型 1代表手机，2代表邮箱
        if(registerType.equals("1")){ //手机注册 包含字段：注册角色，姓名，工作单位，手机号
            String phonnumber = sysUser.getPhonenumber();
            if(StringUtils.isEmpty(phonnumber)){
                return AjaxResult.error("手机号不能为空");
            }else {
                //判断手机号是否已经被注册
                n = sysUserService.isRegister(sysUser);
            }
        }else if(registerType.equals("2")){ //邮箱注册 包含字段：注册角色，姓名，工作单位，邮箱，密码
            String email = sysUser.getEmail();
            if(StringUtils.isEmpty(email)){
                return AjaxResult.error("邮箱不能为空");
            }else{
                n = sysUserService.isRegister(sysUser);
            }
        }
        return AjaxResult.success(n);
    }

    /**
     * 注册方法
     * @param sysUser 用户注册（手机注册或者邮箱注册）
     * @return 结果
     */
    @PostMapping("/register")
    public AjaxResult register(@RequestBody SysUser sysUser)
    {
        String roleType = sysUser.getRoleType();
        String nickName = sysUser.getNickName();
        String deptName = sysUser.getDeptName();
        String code = sysUser.getCode();//验证码
        String uuid = sysUser.getUuid();//唯一识别码
        //都不能为空
        if(roleType == null){
            return AjaxResult.error("角色类型不能为空");
        }
        if(nickName == null){
            return AjaxResult.error("用户姓名不能为空");
        }
        if(deptName == null){
            return AjaxResult.error("工作单位不能为空");
        }

        //注册类型
        String registerType = sysUser.getRegisterType();//注册类型 1代表手机，2代表邮箱
        if(registerType.equals("1")){ //手机注册 包含字段：注册角色，姓名，工作单位，手机号
            String phonnumber = sysUser.getPhonenumber();
            if(StringUtils.isEmpty(phonnumber)){
                return AjaxResult.error("手机号不能为空");
            }else {

                //从redis中获取
                String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + code + StringUtils.nvl(uuid, "");
                String captcha = redisCache.getCacheObject(verifyKey);
                redisCache.deleteObject(verifyKey);
                if(!code.equals(captcha)){
                    return AjaxResult.error("验证码不正确");
                }

                //判断手机号是否已经被注册
                int n = sysUserService.isRegister(sysUser);
               if(n > 0){ //存在，提示
                   return AjaxResult.error("手机号已经被注册！");
               }
                sysUser.setRegisterType("1");
            }
        }else if(registerType.equals("2")){ //邮箱注册 包含字段：注册角色，姓名，工作单位，邮箱，密码
            String email = sysUser.getEmail();
            if(StringUtils.isEmpty(email)){
                return AjaxResult.error("邮箱不能为空");
            }else{
                int n = sysUserService.isRegister(sysUser);
                if(n > 0){ //存在，提示
                    return AjaxResult.error("邮箱已经被注册！");
                }
                sysUser.setRegisterType("2");
                sysUser.setUserName(sysUser.getEmail());
                String password = SecurityUtils.encryptPassword(sysUser.getPassword());
                sysUser.setPassword(password);
            }
        }
        sysUser.setCreateBy(sysUser.getUserName());
        sysUser.setAuditStatus("0"); // 待审核
        sysUser.setIsRegister("1");//已注册
        sysUser.setStatus("1");//默认冻结
        return toAjax(sysUserService.insertUser(sysUser));
    }

    @PutMapping("/resetPwd")
    public AjaxResult resetPwd(@RequestBody SysUser user)
    {
        sysUserService.checkUserAllowed(user);
        sysUserService.checkUserDataScope(user.getUserId());
        user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
        user.setUpdateBy(getUsername());
        return toAjax(sysUserService.resetPwd(user));
    }


    /*
        工作台
        1、用户总数，审核通过数，不通过数，待审核数，在线数（待定）
        2、回复总数，处理中，已处理
        3、待回复留言
        4、待审核用户（分页）
     */
    @GetMapping("getUserAndMessage")
    public AjaxResult getUserAndMessage()
    {
        return AjaxResult.success(sysUserService.getUserAndMessage());
    }


    /**
     * 邮箱登录
     *
     * @param user 邮箱登录
     * @return 结果
     */
    @PostMapping("/emailLogin")
    public AjaxResult emailLogin(@RequestBody SysUser user)
    {
        user.setEmail(user.getUserName());
        List<SysUser> list = sysUserService.selectUserByPhoneOrEmail(user);
        SysUser sysUser = new SysUser();
        if(list.size() == 0){
            return AjaxResult.error("您尚未注册账号，请通过“立即注册”按钮进行注册账号!");
        }
        else if(list.size() == 1){
            sysUser = list.get(0);
            if(StringUtils.isNotEmpty(sysUser.getAuditStatus()) && sysUser.getAuditStatus().equals("0")){
                return AjaxResult.error("该账号未审核，无法登录");
            }else if (StringUtils.isNotEmpty(sysUser.getAuditStatus()) && sysUser.getAuditStatus().equals("2")){
                return AjaxResult.error("该账号审核未通过，无法登录");
            }else if(StringUtils.isNotEmpty(sysUser.getStatus())&&sysUser.getStatus().equals("1")){
                return AjaxResult.error("该账号已被停用，无法登录");
            }
        }else{
            return AjaxResult.error("账号异常");
        }
        AjaxResult ajax = AjaxResult.success();
        // 生成令牌
        String token = loginService.getToken(user.getEmail(), user.getPassword());
        ajax.put(Constants.TOKEN, token);
        return ajax;
    }


    /**
     * 手机登录
     *
     * @param user 手机登录
     * @return 结果
     */
    @PostMapping("/phoneLogin")
    public AjaxResult phoneLogin(@RequestBody SysUser user)
    {
        String code = user.getCode();
        System.out.println("登录验证码：" +code);
        String uuid = user.getUuid();
        if(StringUtils.isNotEmpty(code) && StringUtils.isNotEmpty(uuid)){
            //从redis中获取
            String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + code + StringUtils.nvl(uuid, "");
            String captcha = redisCache.getCacheObject(verifyKey);
            redisCache.deleteObject(verifyKey);
            if(!code.equals(captcha)){
                return AjaxResult.error("验证码不正确");
            }
        }else{
            return AjaxResult.error("验证码不能为空");
        }

        List<SysUser> list = sysUserService.selectUserByPhoneOrEmail(user);
        SysUser sysUser = new SysUser();
        if(list.size() == 0){
            return AjaxResult.error("您尚未注册账号，请通过“立即注册”按钮进行注册账号!");
        }
        else if(list.size() == 1){
            sysUser = list.get(0);
            if(StringUtils.isNotEmpty(sysUser.getAuditStatus()) && sysUser.getAuditStatus().equals("0")){
                return AjaxResult.error("该账号未审核，无法登录");
            }else if (StringUtils.isNotEmpty(sysUser.getAuditStatus()) && sysUser.getAuditStatus().equals("2")){
                return AjaxResult.error("该账号审核未通过，无法登录");
            }else if(StringUtils.isNotEmpty(sysUser.getStatus())&&sysUser.getStatus().equals("1")){
                return AjaxResult.error("该账号已被停用，无法登录");
            }
        }else{
            return AjaxResult.error("账号异常");
        }

        AjaxResult ajax = AjaxResult.success();
        // 生成令牌
        String token = loginService.loginByTelephone(user.getPhonenumber(),code);
        ajax.put(Constants.TOKEN, token);
        return ajax;
    }

    /*
        校验邮箱验证码
     */
    @PostMapping("/emailCodeIsCorrect")
    public AjaxResult emailCodeIsCorrect(@RequestBody SysUser user)
    {
        String code = user.getCode();
        String uuid = user.getUuid();
        System.out.println("登录验证码：" +code);
        if(StringUtils.isNotEmpty(code) && StringUtils.isNotEmpty(uuid)){
            //从redis中获取
            String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + code + StringUtils.nvl(uuid, "");
            String captcha = redisCache.getCacheObject(verifyKey);
            redisCache.deleteObject(verifyKey);
            if(!code.equals(captcha)){
                return AjaxResult.error("验证码不正确");
            }
        }else{
            return AjaxResult.error("验证码不能为空");
        }
        return AjaxResult.success();
    }

}
